# -*- coding: utf-8 -*-
"""
定时任务服务
"""

import logging
from apscheduler.schedulers.background import BackgroundScheduler
from pytz import timezone
from apscheduler.triggers.cron import CronTrigger
from apscheduler.events import EVENT_JOB_EXECUTED, EVENT_JOB_ERROR
# 动态导入（在__init__中处理）
from utils.trade_calendar import TradeCalendar


class SchedulerService:
    """定时任务服务类"""
    
    def __init__(self):
        # 使用配置的时区，默认Asia/Shanghai
        try:
            from config.config import SCHEDULER
            tzname = SCHEDULER.get('timezone', 'Asia/Shanghai')
        except Exception:
            tzname = 'Asia/Shanghai'
        self.scheduler = BackgroundScheduler(timezone=timezone(tzname))
        
        # 动态导入TradeService
        from services.trade_service import TradeService
        self.trade_service = TradeService()
        
        self.trade_calendar = TradeCalendar()
        self.logger = logging.getLogger(__name__)
        
        # 添加任务执行监听器
        self.scheduler.add_listener(self._job_listener, EVENT_JOB_EXECUTED | EVENT_JOB_ERROR)
    
    def start(self):
        """启动定时任务"""
        try:
            # 添加买入任务 - 每个工作日 9:30 执行
            self.scheduler.add_job(
                func=self._execute_buy_task_with_check,
                trigger=CronTrigger(day_of_week='mon-fri', hour=9, minute=30),
                id='buy_task',
                name='股票买入任务',
                misfire_grace_time=300  # 5分钟容错时间
            )
            
            # 添加收盘统计任务 - 每个工作日 15:00 执行
            self.scheduler.add_job(
                func=self._execute_sell_task_with_check,
                trigger=CronTrigger(day_of_week='mon-fri', hour=15, minute=0),
                id='sell_task',
                name='收盘统计任务',
                misfire_grace_time=300  # 5分钟容错时间
            )
            
            # 添加汇总报告任务 - 每个工作日 15:30 执行
            self.scheduler.add_job(
                func=self._generate_daily_report,
                trigger=CronTrigger(day_of_week='mon-fri', hour=15, minute=30),
                id='report_task',
                name='每日汇总报告',
                misfire_grace_time=300
            )
            
            # 启动调度器
            self.scheduler.start()
            self.logger.info("定时任务服务启动成功")
            
            # 打印已添加的任务
            jobs = self.scheduler.get_jobs()
            for job in jobs:
                self.logger.info(f"已添加任务: {job.name} (ID: {job.id})")
            
        except Exception as e:
            self.logger.error(f"定时任务服务启动失败: {e}")
            raise

    def catchup_if_missed(self):
        """补触发：若当天9:30买入任务错过且无当日买入记录，则立即执行一次买入任务。
        典型场景：宕机/停电后在9:30之后启动系统。
        """
        try:
            from datetime import datetime, time, date
            now = datetime.now(self.scheduler.timezone)
            is_trade_day = self.trade_calendar.is_trade_day(now.date())
            if not is_trade_day:
                self.logger.info("今日非交易日，补触发检查跳过")
                return False

            buy_cutoff = now.replace(hour=9, minute=30, second=0, microsecond=0)
            if now <= buy_cutoff:
                self.logger.info("当前尚未到达9:30，无需补触发")
                return False

            # 检查当日是否已有买入记录
            if hasattr(self.trade_service, 'db_manager') and self.trade_service.db_manager:
                has_today = self.trade_service.db_manager.has_buy_records_for_date(now.date())
                if has_today:
                    self.logger.info("当日已有买入记录，无需补触发")
                    return False

            self.logger.info("检测到错过9:30且当日无买入记录，执行一次补触发买入任务")
            self._execute_buy_task_with_check()
            return True
        except Exception as e:
            self.logger.error(f"补触发检查失败: {e}")
            return False
    
    def stop(self):
        """停止定时任务"""
        try:
            self.scheduler.shutdown(wait=True)
            self.logger.info("定时任务服务已停止")
        except Exception as e:
            self.logger.error(f"停止定时任务服务失败: {e}")
    
    def _execute_buy_task_with_check(self):
        """执行买入任务（带交易日检查）"""
        try:
            if self.trade_calendar.is_trade_day():
                self.logger.info("开始执行买入任务")
                self.trade_service.execute_buy_task()
            else:
                self.logger.info("今日非交易日，跳过买入任务")
        except Exception as e:
            self.logger.error(f"买入任务执行异常: {e}")
    
    def _execute_sell_task_with_check(self):
        """执行收盘统计任务（带交易日检查）"""
        try:
            if self.trade_calendar.is_trade_day():
                self.logger.info("开始执行收盘统计任务")
                self.trade_service.execute_sell_task()
            else:
                self.logger.info("今日非交易日，跳过收盘统计任务")
        except Exception as e:
            self.logger.error(f"收盘统计任务执行异常: {e}")
    
    def _generate_daily_report(self):
        """生成每日汇总报告"""
        try:
            if self.trade_calendar.is_trade_day():
                summary = self.trade_service.get_trading_summary()
                if summary:
                    self.logger.info("=== 每日交易汇总 ===")
                    self.logger.info(f"总股票数: {summary.get('total_stocks', 0)}")
                    self.logger.info(f"完成监听: {summary.get('completed_stocks', 0)}")
                    self.logger.info(f"正在监听: {summary.get('active_stocks', 0)}")
                    self.logger.info(f"平均收益: {summary.get('average_return', 0)}%")
                    self.logger.info(f"最高收益: {summary.get('max_return', 0)}%")
                    self.logger.info(f"最低收益: {summary.get('min_return', 0)}%")
                    self.logger.info("==================")
                else:
                    self.logger.warning("无法生成交易汇总报告")
        except Exception as e:
            self.logger.error(f"生成每日汇总报告异常: {e}")
    
    def _job_listener(self, event):
        """任务执行监听器"""
        job_id = event.job_id
        if event.exception:
            self.logger.error(f"任务 {job_id} 执行失败: {event.exception}")
        else:
            self.logger.info(f"任务 {job_id} 执行成功")
    
    def get_job_status(self):
        """获取任务状态"""
        try:
            jobs = self.scheduler.get_jobs()
            job_list = []
            for job in jobs:
                job_info = {
                    'id': job.id,
                    'name': job.name,
                    'next_run': str(job.next_run_time) if job.next_run_time else 'N/A',
                    'trigger': str(job.trigger)
                }
                job_list.append(job_info)
            return job_list
        except Exception as e:
            self.logger.error(f"获取任务状态失败: {e}")
            return []
    
    def run_job_now(self, job_id: str):
        """立即运行指定任务"""
        try:
            job = self.scheduler.get_job(job_id)
            if job:
                job.modify(next_run_time=None)  # 立即执行
                self.logger.info(f"任务 {job_id} 已加入执行队列")
                return True
            else:
                self.logger.warning(f"未找到任务: {job_id}")
                return False
        except Exception as e:
            self.logger.error(f"运行任务 {job_id} 失败: {e}")
            return False
